package edu.stanford.prpl.common.util;

import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;

import edu.stanford.prpl.api.BlobResource;
import edu.stanford.prpl.api.Group;
import edu.stanford.prpl.api.Identity;
import edu.stanford.prpl.api.PRPLObjectManager;
import edu.stanford.prpl.api.Resource;

public class TypeValuePairUtil {

	public static final String PRPL_RESOURCE = "prpl-resource";
	public static final String PRPL_BLOBRESOURCE = "prpl-blobresource";
	public static final String PRPL_GROUP = "prpl-group";
	public static final String PRPL_IDENTITY = "prpl-identity";

	// TODO: convert other types into constants.

	public static String[] toTypeValuePair(Object value) {
		if (value instanceof Integer) {
			return new String[] { "int", value.toString() };
		} else if (value instanceof Float) {
			return new String[] { "float", value.toString() };
		} else if (value instanceof Double) {
			return new String[] { "double", value.toString() };
		} else if (value instanceof Long) {
			return new String[] { "long", value.toString() };
		} else if (value instanceof Boolean) {
			return new String[] { "boolean", value.toString() };
		} else if (value instanceof Calendar) {
			return new String[] { "calendar", Long.toString(((Calendar) value).getTimeInMillis()) };
		} else if (value instanceof Date) {
			DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL);
			return new String[] { "calendar", dateFormat.format((Date) value) };
		} else if (value instanceof String) {
			return new String[] { "string", value.toString() };
		} else if (value instanceof Short) {
			return new String[] { "short", value.toString() };
		} else if (value instanceof BlobResource) {
			return new String[] { PRPL_BLOBRESOURCE, ((BlobResource) value).getURI() };
		} else if (value instanceof Resource) {
			return new String[] { PRPL_RESOURCE, ((Resource) value).getURI() };
		} else if (value instanceof Group) {
			return new String[] { PRPL_GROUP, ((Group) value).getURI() };
		} else if (value instanceof Identity) {
			return new String[] { PRPL_IDENTITY, ((Identity) value).getURI() };
		} else {
			return new String[] { "unknown", value == null ? "null" : value.toString() };
		}
	}

	public static Object fromTypeValuePair(String[] typeValuePair, PRPLObjectManager prplObjectManager) {

		if (typeValuePair.length != 2) {
			throw new IllegalArgumentException("Argument must be String[] of length 2!");
		}

		String type = typeValuePair[0];
		String value = typeValuePair[1];

		if (type.equals("int")) {
			return Integer.valueOf(value);
		} else if (type.equals("float")) {
			return Float.valueOf(value);
		} else if (type.equals("double")) {
			return Double.valueOf(value);
		} else if (type.equals("long")) {
			return Long.valueOf(value);
		} else if (type.equals("boolean")) {
			return Boolean.valueOf(value);
		} else if (type.equals("calendar")) {
			Calendar calendar = Calendar.getInstance();
			calendar.setTimeInMillis(Long.valueOf(value));
			return calendar;
		} else if (type.equals("string")) {
			return value;
		} else if (type.equals("short")) {
			return Short.valueOf(value);
		} else if (type.equals(PRPL_BLOBRESOURCE)) {
			return prplObjectManager.getResourceManager().getBlobResource(value);
		} else if (type.equals(PRPL_RESOURCE)) {
			return prplObjectManager.getResourceManager().getResource(value);
		} else if (type.equals(PRPL_GROUP)) {
			return prplObjectManager.getGroupManager().getGroupByURI(value);
		} else if (type.equals(PRPL_IDENTITY)) {
			return prplObjectManager.getIdentityManager().getIdentityByURI(value, true);
		} else {
			return value;
		}
	}

	public static Object[] deserializeTypeValuePairs(Object[] pairs, PRPLObjectManager prplObjectManager) {
		Object[] values = new Object[pairs.length];
		// deserialize typeValuePairs to values
		for (int i = 0; i < pairs.length; i++) {
			Object[] pair = (Object[]) pairs[i];
			String[] typeValuePair = new String[] { (String) pair[0], (String) pair[1] };
			values[i] = fromTypeValuePair(typeValuePair, prplObjectManager);
		}
		return values;
	}
}
